// src/components/WebgiViewer.jsx
import {
    ViewerApp,
    AssetManagerPlugin,
    GBufferPlugin,
    timeout,
    ProgressivePlugin,
    TonemapPlugin,
    SSRPlugin,
    SSAOPlugin,
    DiamondPlugin,
    FrameFadePlugin,
    GLTFAnimationPlugin,
    GroundPlugin,
    BloomPlugin,
    TemporalAAPlugin,
    AnisotropyPlugin,
    GammaCorrectionPlugin,

    addBasePlugins,
    // ITexture, TweakpaneUiPlugin, AssetManagerBasicPopupPlugin, CanvasSnipperPlugin,
    CanvasSnipperPlugin,

    // IViewerPlugin, FileTransferPlugin,

    // Color, // Import THREE.js internals
    // Texture, // Import THREE.js internals

    mobileAndTabletCheck,
} from 'webgi'
import {useCallback, useEffect, useRef, forwardRef, useImperativeHandle, useState} from 'react'
import {ScrollTrigger} from 'gsap/ScrollTrigger'
import gsap from 'gsap'
import {scrollAnimation} from "../lib/scroll-animation.js";

gsap.registerPlugin(ScrollTrigger)

const WebgiViewer = forwardRef((props, ref) => {
    const canvasRef = useRef(null);
    const [viewerRef, setViewerRef] = useState(null);
    const [targetRef, setTargetRef] = useState(null);
    const [cameraRef, setCameraRef] = useState(null);
    const [positionRef, setPositionRef] = useState(null);
    const canvasContainerRef = useRef(null);
    // 是否处于模型预览
    const [previewMode, setPreviewMode] = useState(false);
    // 移动端
    const [isMobile, setIsMobile] = useState(false);

    // 自定义ref的公开值
    useImperativeHandle(ref, () => ({
        triggerPreview() {
            setPreviewMode(true)
            // 可以接收鼠标信号
            canvasContainerRef.current.style.pointerEvents = 'all'
            props.contentRef.current.style.opacity = '0'

            gsap.to(positionRef, {
                x: 13.04,
                y: -2.01,
                z: 2.29,
                duration: 2,
                onUpdate: () => {
                    viewerRef.setDirty()
                    cameraRef.positionTargetUpdated(true)
                }
            })

            gsap.to(targetRef, {x: 0.11, y: 0.0, z: 0.0, duration: 2})

            // 允许操作模型
            viewerRef.scene.activeCamera.setCameraOptions({controlsEnabled: true})
        }
    }))

    const memorizedScrollAnimation = useCallback(
        (position, target, isMobile, onUpdate) => {
            if (position && target && onUpdate) {
                scrollAnimation(position, target, isMobile, onUpdate)
            }
        }, [])

    const setupViewer = useCallback(async () => {
        // Initialize the viewer
        const viewer = new ViewerApp({
            // canvas: document.getElementById('webgi-canvas') as HTMLCanvasElement,
            canvas: canvasRef.current,
        })
        setViewerRef(viewer)
        // 是不是移动端
        const isMobileOrTablet = mobileAndTabletCheck()
        setIsMobile(isMobileOrTablet)

        const manager = await viewer.addPlugin(AssetManagerPlugin)

        const camera = viewer.scene.activeCamera;
        const position = camera.position
        const target = camera.target

        setCameraRef(camera)
        setPositionRef(position)
        setTargetRef(target)

        // Add plugins individually.
        await viewer.addPlugin(GBufferPlugin)
        await viewer.addPlugin(new ProgressivePlugin(32))
        // await viewer.addPlugin(new TonemapPlugin(!viewer.useRgbm))
        await viewer.addPlugin(new TonemapPlugin(true))
        await viewer.addPlugin(GammaCorrectionPlugin)
        await viewer.addPlugin(SSRPlugin)
        await viewer.addPlugin(SSAOPlugin)
        await viewer.addPlugin(BloomPlugin)

        viewer.renderer.refreshPipeline()

        // Import and add a GLB file.
        // await viewer.load("scene-black.glb")
        await manager.addFromPath("scene-black.glb")

        // 默认背景是一大片黑的, 会影响其他页面, 这里裁剪
        viewer.getPlugin(TonemapPlugin).config.clipBackground = true

        viewer.scene.activeCamera.setCameraOptions({controlsEnabled: false})

        if (isMobileOrTablet) {
            position.set(-16.7, 1.17, 11.7)
            target.set(0, 1.37, 0)
            // hide img
            props.contentRef.current.className = "mobile-or-tablet"
        }

        window.scrollTo(0, 0)

        let needsUpdate = true

        const onUpdate = () => {
            needsUpdate = true
            viewer.setDirty()
        }

        viewer.addEventListener('preFrame', () => {
            if (needsUpdate) {
                camera.positionTargetUpdated(true)
                needsUpdate = false
            }
        })

        memorizedScrollAnimation(position, target, isMobileOrTablet, onUpdate)
    }, [])

    useEffect(() => {
        setupViewer()
    }, []);

    const handleExit = useCallback(() => {
        setPreviewMode(false)
        canvasContainerRef.current.style.pointerEvents = 'all'
        viewerRef.scene.activeCamera.setCameraOptions({controlsEnabled: false})
        props.contentRef.current.style.opacity = '1'

        gsap.to(positionRef, {
            x: !isMobile ? 1.56 : 9.36,
            y: !isMobile ? 5.0 : 10.95,
            z: !isMobile ? 0.01 : 0.09,
            scrollTrigger: {
                // .display-section的dom元素触发该动画
                trigger: '.display-section',
                start: 'top bottom',
                end: 'top top',
                scrub: 2,
                immediateRender: false
            },
            onUpdate: () => {
                viewerRef.setDirty()
                cameraRef.positionTargetUpdated(true)
            }
        })

        // 相机的target -> model
        gsap.to(targetRef, {
            x: !isMobile ? -0.55 : -1.62,
            y: !isMobile ? 0.32 : 0.02,
            z: !isMobile ? 0.0 : -0.06,
            scrollTrigger: {
                // .display-section的dom元素触发该动画
                trigger: '.display-section',
                start: 'top bottom',
                end: 'top top',
                scrub: 2,
                immediateRender: false
            },
        })
    }, [canvasContainerRef, viewerRef, positionRef, cameraRef, targetRef])

    return (
        <div ref={canvasContainerRef} id={'webgi-canvas-container'}>
            <canvas id={'webgi-canvas'} ref={canvasRef}/>
            {previewMode && (
                <button className={'button'} onClick={handleExit}>Exit</button>
            )}
        </div>
    )
})

export default WebgiViewer
